package semantic.rules.postprocess

import scala.collection.mutable.Buffer
import semantic.CLabels._
import semantic.COperations._

object CPostProcessRuleIfElse extends CPostProcessRule
{
    override def apply()(implicit code:Buffer[String]) =
    {
        val lblsIfGt = collection.mutable.HashMap[Long, Int]()
        val lblsIfElsEnd = collection.mutable.HashMap[Long, Int]()
        def findLabels(from:Int = 0, i:Int = 0):Int =
        {
            if (i >= code.size) return i

            val ln = code(i)

            if (ln contains s"$LABEL_IF_GOTO") lblsIfGt += extractID(ln) -> (i + 2 - from)
            else if (ln contains s"$LABEL_IF_ELSE_END") lblsIfElsEnd += extractID(ln) -> (i + 1 - from)

            if (ln startsWith FUNC) findLabels(from, findLabels(i + 1, i + 1))
            else if (ln startsWith END) i + 1
            else findLabels(from, i + 1)
        }

        findLabels()

        code.foldLeft(0)((i, v) =>
        {
            if (v startsWith s"$PUSH $LABEL_IF_ELSE_TARGET")
            {
                val id = extractID(v)
                code(i) = v replace (s"$LABEL_IF_ELSE_TARGET$id", lblsIfGt(id) toString)
            }
            else if (v startsWith s"$PUSH $LABEL_IF_GOTO")
            {
                val id = extractID(v)
                code(i) = v replace (s"$LABEL_IF_GOTO$id", lblsIfElsEnd(id) toString)
            }
            i + 1
        })

        val fltrd = code map (s =>
            if (s contains LABEL_IF_ELSE_END) s replace (s"$LABEL_IF_ELSE_END${extractID(s)}", "") else s)
        code.clear()
        code ++= fltrd
    }

    private def extractID(string:String) = string substring ((string lastIndexOf LABEL_TERMINATOR) + 1) toLong
}
